﻿// ***********************************************************************
// Assembly         : Tx.OCC
// Author           : tianteng
// Created          : 03-09-2021
//
// Last Modified By : tianteng
// Last Modified On : 01-26-2021
// ***********************************************************************
// <copyright file="OcctTopo2dEx.cs" company="Tobias Schachte">
//     Copyright © 2015-2021 Tobias Schachte
// </copyright>
// <summary></summary>
// ***********************************************************************
using Occt;
using System.Collections.Generic;
using System.Linq;

namespace Tx.OCC
{
    /// <summary>
    /// Class OcctTopo2dEx.
    /// </summary>
    public static class OccTopo2dEx
    {
        /// <summary>
        /// Transforms the sketch shape.
        /// </summary>
        /// <param name="original">The original.</param>
        /// <param name="transforms">The transforms.</param>
        /// <param name="includeOriginal">if set to <c>true</c> [include original].</param>
        /// <returns>TopoDS_Shape.</returns>
        public static TopoDS_Shape TransformSketchShape(TopoDS_Shape original, IEnumerable<gp_Trsf2d> transforms, bool includeOriginal)
        {
            // Make copies
            var builder = new BRep_Builder();
            var shapeBuildEdge = new ShapeBuild_Edge();
            builder.MakeCompound(out TopoDS_Compound newShape);

            foreach (var transform in transforms)
            {
                foreach (var wire in original.Wires())
                {
                    foreach (var edge in wire.Edges())
                    {
                        if (includeOriginal)
                            builder.Add(newShape, edge);

                        var tedge = edge.TShape as BRep_TEdge;
                        var curves = tedge.Curves.ToList();
                        foreach (BRep_CurveOnSurface curveRep in curves.OfType<BRep_CurveOnSurface>())
                        {
                            // Transform PCurve
                            var curve = curveRep.PCurve;
                            double first = curve.FirstParameter;
                            double last = curve.LastParameter;
                            var newCurve = shapeBuildEdge.TransformPCurve(curve, transform, 1.0, ref first, ref last);

                            // Transform UVs
                            gp_Pnt2d uv0 = new gp_Pnt2d();
                            gp_Pnt2d uv1 = new gp_Pnt2d();
                            curveRep.UVPoints(out uv0, out uv1);
                            uv0.Transform(transform);
                            uv1.Transform(transform);
                            var makeEdge = new BRepBuilderAPI_MakeEdge2d(newCurve, uv0, uv1);
                            builder.Add(newShape, makeEdge.Edge);
                        }
                    }
                }
            }

            return BuildWiresFromEdges(newShape);
        }

        /// <summary>
        /// Builds the wires from edges.
        /// </summary>
        /// <param name="shape">The shape.</param>
        /// <returns>TopoDS_Shape.</returns>
        public static TopoDS_Shape BuildWiresFromEdges(TopoDS_Shape shape)
        {
            var edges = new TopTools_HSequenceOfShape();
            foreach (var edge in shape.Edges())
            {
                edges.Append(edge);
            }

            ShapeAnalysis_FreeBounds.ConnectEdgesToWires(edges, 1e-8, false, out TopTools_HSequenceOfShape wires);

            var builder = new BRep_Builder();
            builder.MakeCompound(out TopoDS_Compound newShape);
            var wiresSequence = wires.Sequence;
            for (int i = wiresSequence.Lower; i <= wiresSequence.Upper; i++)
            {
                builder.Add(newShape, wiresSequence[i]);
            }

            return newShape;
        }
    }
}